package cn.itcast.zt.resthandler;

import cn.itcast.zt.beans.MethodInfo;
import cn.itcast.zt.beans.ServerInfo;
import cn.itcast.zt.interfaces.RestHandler;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;
import reactor.core.publisher.Mono;

/**
 * created by zhangtian on 2018/7/9
 */
public class WebClientRestHandler implements RestHandler {

    private WebClient webClient ;
    private RequestBodySpec request;

    /**
     * 初始化webclient
     * @param serverInfo
     */
    @Override
    public void init(ServerInfo serverInfo) {
        this.webClient = WebClient.create(serverInfo.getUrl()) ;
    }

    /**
     * 处理rest请求
     * @param methodInfo
     * @return
     */
    @Override
    public Object invokeRest(MethodInfo methodInfo) {
        // 返回结果
        Object result =null ;
        request = this.webClient
                // 请求方法
                .method(methodInfo.getMethod())
                // 请求URL
                .uri(methodInfo.getUrl(), methodInfo.getParams())
                .accept(MediaType.APPLICATION_JSON) ;

        WebClient.ResponseSpec retrieve = null;
        // 判断是否带了Body
        if(methodInfo.getBody() != null){
            // 发送请求
            // 发出请求
            retrieve = request
                        .body(methodInfo.getBody(), methodInfo.getBodyElementType())
                        .retrieve();
        }else {
            retrieve = request.retrieve();
        }

        // 处理异常
        retrieve.onStatus(status->status.value() == 404, response->Mono.just(new RuntimeException("Not Found"))) ;

        // 请求body
        if(methodInfo.isReturnFlux()){
            result = retrieve.bodyToFlux(methodInfo.getReturnElementType()) ;
        }else {
            result = retrieve.bodyToMono(methodInfo.getReturnElementType()) ;
        }
        return result;
    }
}
